<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CPU时空分析系统</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/luxon@3.0.1"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.2.0"></script>
    <style>
        :root {
            --primary: #4361ee;
            --warning: #f8961e;
            --danger: #ef233c;
            --success: #2ec4b6;
            --dark: #2b2d42;
        }

        body {
            background-color: #f8f9fa;
            font-family: 'Segoe UI', system-ui, sans-serif;
        }

        .dashboard-header {
            background: linear-gradient(135deg, var(--dark) 0%, var(--primary) 100%);
            color: white;
            padding: 1.5rem 0;
            margin-bottom: 2rem;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
        }

        .analysis-card {
            border-radius: 10px;
            margin-bottom: 2rem;
            box-shadow: 0 4px 6px rgba(0,0,0,0.05);
            background: white;
        }

        .chart-container {
            position: relative;
            height: 400px;
            margin-bottom: 1rem;
        }

        .host-selector {
            max-width: 300px;
        }

        .core-selector {
            max-width: 300px;
        }

        .time-slider {
            width: 100%;
        }

        .badge-cpu {
            font-size: 0.75rem;
            font-weight: 500;
        }

        .filter-controls {
            background: white;
            padding: 1rem;
            border-radius: 8px;
            margin-bottom: 1rem;
            box-shadow: 0 2px 4px rgba(0,0,0,0.05);
        }

        .core-badge {
            font-size: 0.8rem;
            background-color: #e9ecef;
            color: #495057;
        }

        .legend-item.disabled {
            opacity: 0.5;
            pointer-events: none;
        }
    </style>
</head>
<body>
    <div class="dashboard-header">
        <div class="container">
            <h1><i class="bi bi-cpu"></i> CPU时空分析系统</h1>
            <p class="mb-0">主机名、CPU核心与时间维度联合分析</p>
        </div>
    </div>

    <div class="container">
        {% if data and data.data %}
        <!-- 控制面板 -->
        <div class="filter-controls">
            <div class="row g-3">
                <div class="col-md-4">
                    <label for="hostSelector" class="form-label">主机名</label>
                    <select class="form-select host-selector" id="hostSelector">
                        <option value="">所有主机</option>
                        {% set hosts = [] %}
                        {% for item in data.data %}
                            {% if item.hostname not in hosts %}
                                {% set _ = hosts.append(item.hostname) %}
                                <option value="{{ item.hostname }}">{{ item.hostname }}</option>
                            {% endif %}
                        {% endfor %}
                    </select>
                </div>
                <div class="col-md-4">
                    <label for="coreSelector" class="form-label">CPU核心</label>
                    <select class="form-select core-selector" id="coreSelector">
                        <option value="">所有核心</option>
                        {% set cores = [] %}
                        {% for item in data.data %}
                            {% if item.cpu_core not in cores %}
                                {% set _ = cores.append(item.cpu_core) %}
                                <option value="{{ item.cpu_core }}">核心 {{ item.cpu_core }}</option>
                            {% endif %}
                        {% endfor %}
                    </select>
                </div>
                <div class="col-md-2">
                    <label for="timeRange" class="form-label">时间范围</label>
                    <input type="range" class="form-range" id="timeRange" min="0" max="100" value="100">
                    <div id="timeRangeValue" class="small text-muted">全部时间</div>
                </div>
                <div class="col-md-2 d-flex align-items-end">
                    <button class="btn btn-primary w-100" id="refreshBtn">
                        <i class="bi bi-arrow-clockwise"></i> 刷新
                    </button>
                </div>
            </div>
        </div>

        <!-- CPU使用率热力图 -->
        <div class="analysis-card">
            <div class="card-header d-flex justify-content-between align-items-center">
                <h5 class="card-title mb-0"><i class="bi bi-grid-3x3"></i> CPU使用率时空热力图</h5>
                <div class="form-check form-switch">
                    <input class="form-check-input" type="checkbox" id="stackToggle" checked>
                    <label class="form-check-label" for="stackToggle">堆叠显示</label>
                </div>
            </div>
            <div class="card-body">
                <div class="chart-container">
                    <canvas id="heatmapChart"></canvas>
                </div>
            </div>
        </div>

        <!-- CPU使用趋势图 -->
        <div class="analysis-card">
            <div class="card-header">
                <div class="d-flex justify-content-between align-items-center">
                    <h5 class="card-title mb-0"><i class="bi bi-graph-up"></i> CPU使用趋势</h5>
                    <div id="hostLegend" class="d-flex flex-wrap gap-2"></div>
                </div>
            </div>
            <div class="card-body">
                <div class="chart-container">
                    <canvas id="trendChart"></canvas>
                </div>
            </div>
        </div>

        <!-- 详细数据表格 -->
        <div class="analysis-card">
            <div class="card-header">
                <h5 class="card-title mb-0"><i class="bi bi-table"></i> 详细数据</h5>
            </div>
            <div class="card-body p-0">
                <div class="table-responsive">
                    <table class="table table-hover mb-0">
                        <thead class="table-light">
                            <tr>
                                <th>时间</th>
                                <th>主机名</th>
                                <th>核心</th>
                                <th>使用率</th>
                                <th>状态</th>
                            </tr>
                        </thead>
                        <tbody id="dataTable">
                            {% for item in data.data %}
                            {% set used = item.cpu_used.split('%')[0] | float %}
                            <tr data-host="{{ item.hostname }}" data-core="{{ item.cpu_core }}" data-time="{{ item.date }}">
                                <td>{{ item.date }}</td>
                                <td>{{ item.hostname }}</td>
                                <td><span class="badge core-badge">{{ item.cpu_core }}</span></td>
                                <td>
                                    <div class="progress" style="height: 20px;">
                                        <div class="progress-bar bg-{{ 'danger' if used > 80 else 'warning' if used > 60 else 'success' }}"
                                             style="width: {{ used }}%">
                                            {{ item.cpu_used }}
                                        </div>
                                    </div>
                                </td>
                                <td>
                                    <span class="badge bg-{{ 'danger' if used > 80 else 'warning' if used > 60 else 'success' }} badge-cpu">
                                        {% if used > 80 %}过载{% elif used > 60 %}高负载{% else %}正常{% endif %}
                                    </span>
                                </td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
        {% else %}
        <div class="alert alert-danger">
            <i class="bi bi-exclamation-triangle"></i> 错误：没有可用的CPU数据
        </div>
        {% endif %}
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        // 1. 数据准备
        const rawData = JSON.parse(`{{ data.data | tojson | safe }}`).map(item => {
            return {
                ...item,
                cpu_used: parseFloat(item.cpu_used.replace('%', '')) || 0,
                timestamp: new Date(item.date).getTime()
            };
        });

        // 2. 数据处理
        function processData() {
            const hosts = [...new Set(rawData.map(item => item.hostname))];
            const cores = [...new Set(rawData.map(item => item.cpu_core))];
            const timestamps = [...new Set(rawData.map(item => item.date))].sort((a, b) => new Date(a) - new Date(b));

            // 构建数据矩阵
            const matrix = {};
            hosts.forEach(host => {
                matrix[host] = {};
                cores.forEach(core => {
                    matrix[host][core] = {};
                    timestamps.forEach(time => {
                        const record = rawData.find(
                            item => item.hostname === host &&
                                  item.cpu_core === core &&
                                  item.date === time
                        );
                        matrix[host][core][time] = record ? {
                            cpu_used: record.cpu_used,
                            hostname: record.hostname,
                            cpu_core: record.cpu_core
                        } : null;
                    });
                });
            });

            return {
                hosts,
                cores,
                timestamps,
                matrix,
                minDate: new Date(timestamps[0]),
                maxDate: new Date(timestamps[timestamps.length - 1])
            };
        }

        // 3. 图表实例
        let heatmapChart, trendChart;
        let processedData = processData();

        // 4. 初始化热力图
        function initHeatmap() {
            const ctx = document.getElementById('heatmapChart');
            if (!ctx) return;

            const datasets = [];
            processedData.hosts.forEach((host, hostIdx) => {
                processedData.cores.forEach((core, coreIdx) => {
                    const color = `hsl(${(hostIdx * 30 + coreIdx * 90) % 360}, 70%, 50%)`;
                    const dataPoints = processedData.timestamps.map(time => {
                        const val = processedData.matrix[host][core][time]?.cpu_used;
                        return val !== undefined ? {
                            x: time,
                            y: val,
                            host: host,
                            core: core
                        } : null;
                    }).filter(Boolean);

                    if (dataPoints.length > 0) {
                        datasets.push({
                            label: `${host} - 核心 ${core}`,
                            data: dataPoints,
                            backgroundColor: color,
                            borderColor: color,
                            borderWidth: 1,
                            host: host,
                            core: core,
                            hidden: false
                        });
                    }
                });
            });

            heatmapChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    datasets: datasets
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        x: {
                            type: 'time',
                            time: {
                                parser: 'yyyy-MM-dd HH:mm:ss',
                                tooltipFormat: 'MM-dd HH:mm',
                                unit: 'minute'
                            },
                            stacked: document.getElementById('stackToggle').checked,
                            title: { display: true, text: '时间' }
                        },
                        y: {
                            min: 0,
                            max: 100,
                            stacked: document.getElementById('stackToggle').checked,
                            title: { display: true, text: '使用率 (%)' }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return `${context.dataset.label}: ${context.parsed.y}%`;
                                },
                                afterLabel: function(context) {
                                    const data = context.dataset.data[context.dataIndex];
                                    if (data && data.host && data.core) {
                                        const record = processedData.matrix[data.host][data.core][data.x];
                                        if (record) {
                                            return `主机: ${record.hostname}\n核心: ${record.cpu_core}`;
                                        }
                                    }
                                    return '';
                                }
                            }
                        }
                    },
                    onClick: function(_, elements) {
                        if (elements.length > 0) {
                            const element = elements[0];
                            const dataset = this.data.datasets[element.datasetIndex];
                            const data = dataset.data[element.index];
                            filterData(dataset.host, dataset.core, data.x);
                        }
                    }
                }
            });
        }

        // 5. 初始化趋势图
        function initTrendChart() {
            const ctx = document.getElementById('trendChart');
            if (!ctx) return;

            const datasets = [];
            const legendContainer = document.getElementById('hostLegend');
            legendContainer.innerHTML = '';

            processedData.hosts.forEach((host, hostIdx) => {
                processedData.cores.forEach((core, coreIdx) => {
                    const color = `hsl(${(hostIdx * 30 + coreIdx * 90) % 360}, 70%, 50%)`;
                    const dataPoints = processedData.timestamps.map(time => {
                        const val = processedData.matrix[host][core][time]?.cpu_used;
                        return val !== undefined ? { x: time, y: val } : null;
                    }).filter(Boolean);

                    if (dataPoints.length > 0) {
                        const datasetId = `${host}-${core}`.replace(/\s+/g, '-');
                        datasets.push({
                            id: datasetId,
                            label: `${host} - 核心 ${core}`,
                            data: dataPoints,
                            borderColor: color,
                            backgroundColor: color + '20',
                            tension: 0.3,
                            fill: true,
                            borderWidth: 2,
                            pointRadius: 3,
                            pointHoverRadius: 5,
                            hidden: false
                        });

                        // 添加图例项
                        const legendItem = document.createElement('div');
                        legendItem.className = 'form-check form-check-inline';
                        legendItem.innerHTML = `
                            <input class="form-check-input trend-legend"
                                   type="checkbox"
                                   id="legend-${datasetId}"
                                   data-dataset="${datasetId}"
                                   checked
                                   style="background-color: ${color}">
                            <label class="form-check-label small" for="legend-${datasetId}">${host} - 核心 ${core}</label>
                        `;
                        legendContainer.appendChild(legendItem);
                    }
                });
            });

            trendChart = new Chart(ctx, {
                type: 'line',
                data: { datasets: datasets },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    interaction: {
                        intersect: false,
                        mode: 'index'
                    },
                    scales: {
                        x: {
                            type: 'time',
                            time: {
                                parser: 'yyyy-MM-dd HH:mm:ss',
                                tooltipFormat: 'MM-dd HH:mm',
                                unit: 'minute'
                            },
                            title: { display: true, text: '时间' },
                            min: processedData.minDate,
                            max: processedData.maxDate
                        },
                        y: {
                            min: 0,
                            max: 100,
                            title: { display: true, text: '使用率 (%)' }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return `${context.dataset.label}: ${context.parsed.y}%`;
                                },
                                afterLabel: function(context) {
                                    const time = context.parsed.x;
                                    const labelParts = context.dataset.label.split(' - 核心 ');
                                    if (labelParts.length === 2) {
                                        const record = processedData.matrix[labelParts[0]][labelParts[1]][new Date(time).toISOString()];
                                        if (record) {
                                            return `主机: ${record.hostname}\n核心: ${record.cpu_core}`;
                                        }
                                    }
                                    return '';
                                }
                            }
                        }
                    }
                }
            });

            // 图例点击事件
            document.querySelectorAll('.trend-legend').forEach(checkbox => {
                checkbox.addEventListener('change', function() {
                    const datasetId = this.dataset.dataset;
                    const dataset = trendChart.data.datasets.find(ds => ds.id === datasetId);
                    if (dataset) {
                        const meta = trendChart.getDatasetMeta(
                            trendChart.data.datasets.indexOf(dataset)
                        );
                        meta.hidden = !this.checked;
                        trendChart.update();
                    }
                });
            });
        }

        // 6. 筛选数据
        function filterData(host, core, time) {
            // 更新筛选器UI
            if (host !== undefined) {
                document.getElementById('hostSelector').value = host || '';
            }
            if (core !== undefined) {
                document.getElementById('coreSelector').value = core || '';
            }

            // 筛选表格数据
            const rows = document.querySelectorAll('#dataTable tr');
            rows.forEach(row => {
                const showHost = !host || row.dataset.host === host;
                const showCore = !core || row.dataset.core === core;
                const showTime = !time || row.dataset.time === time;
                row.style.display = (showHost && showCore && showTime) ? '' : 'none';
            });

            // 更新图表可见性
            updateChartVisibility(host, core);
        }

        // 7. 更新图表可见性
        function updateChartVisibility(host, core) {
            // 更新热力图
            if (heatmapChart) {
                heatmapChart.data.datasets.forEach(dataset => {
                    const shouldShow =
                        (!host || dataset.host === host) &&
                        (!core || dataset.core === core);
                    dataset.hidden = !shouldShow;
                });
                heatmapChart.update();
            }

            // 更新趋势图
            if (trendChart) {
                trendChart.data.datasets.forEach(dataset => {
                    const [datasetHost, datasetCore] = dataset.label.split(' - 核心 ');
                    const shouldShow =
                        (!host || datasetHost === host) &&
                        (!core || datasetCore === core);
                    dataset.hidden = !shouldShow;
                });
                trendChart.update();
            }

            // 更新图例状态
            updateLegendStates(host, core);
        }

        // 8. 更新图例状态
        function updateLegendStates(host, core) {
            document.querySelectorAll('.trend-legend').forEach(checkbox => {
                const datasetId = checkbox.dataset.dataset;
                const dataset = trendChart.data.datasets.find(ds => ds.id === datasetId);
                if (dataset) {
                    const [datasetHost, datasetCore] = dataset.label.split(' - 核心 ');
                    const shouldShow =
                        (!host || datasetHost === host) &&
                        (!core || datasetCore === core);

                    checkbox.checked = shouldShow;
                    const legendItem = checkbox.closest('.form-check');
                    if (shouldShow) {
                        legendItem.classList.remove('disabled');
                        checkbox.disabled = false;
                    } else {
                        legendItem.classList.add('disabled');
                        checkbox.disabled = true;
                    }
                }
            });
        }

        // 9. 初始化页面
        document.addEventListener('DOMContentLoaded', () => {
            try {
                initHeatmap();
                initTrendChart();

                // 事件监听
                document.getElementById('hostSelector').addEventListener('change', () => {
                    filterData(document.getElementById('hostSelector').value);
                });

                document.getElementById('coreSelector').addEventListener('change', () => {
                    filterData(null, document.getElementById('coreSelector').value);
                });

                document.getElementById('stackToggle').addEventListener('change', function() {
                    if (heatmapChart) {
                        heatmapChart.options.scales.x.stacked = this.checked;
                        heatmapChart.options.scales.y.stacked = this.checked;
                        heatmapChart.update();
                    }
                });

                document.getElementById('timeRange').addEventListener('input', function() {
                    const percent = parseInt(this.value);
                    const timeDiff = processedData.maxDate - processedData.minDate;
                    const newMinDate = new Date(processedData.minDate.getTime() + timeDiff * percent / 100);

                    if (trendChart) {
                        trendChart.options.scales.x.min = newMinDate;
                        trendChart.update();
                    }

                    document.getElementById('timeRangeValue').textContent =
                        percent === 100 ? '全部时间' : `最近 ${100 - percent}% 时间范围`;
                });

                document.getElementById('refreshBtn').addEventListener('click', () => {
                    window.location.reload();
                });

            } catch (err) {
                console.error("初始化失败:", err);
            }
        });
    </script>
</body>
</html>